package com.xc.quickstart.manager.oa;

import com.alibaba.fastjson.JSON;
import com.xc.quickstart.common.context.ApiContext;
import com.xc.quickstart.common.model.ApiResponse;
import com.xc.quickstart.common.util.HttpClientUtil;
import com.xc.quickstart.manager.oa.model.*;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.time.Duration;
import java.time.Instant;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author wzp
 * @version 1.0
 * @description OA系统调用接口
 * @date 2021/1/8 11:34
 */
@Component
@Slf4j
public class OaBizManager {

    @Autowired
    private OaClient oaClient;


    private static final String APPKEY = "VJbJPC3l";

    private static final String APPSECRET = "5d36be0cc3290ea5ab77dec6547b9cbeceffdb7b";

    private static final String DEFAULT_KEY = "XCKJOPENADMINZNB";

    /**
     * 人员信息获取递归类型
     * 1=不包含子部门员工及信息
     * 2=包含子部门员工及信息
     */
    private static final String RECURSION_FLAG = "1";

    @Value("${oa.root_path}")
    private String oaApi;

    private static final String ADMIN_URL = "/oa/api/employee/getEmpByDeptId";

    private static final String ADMIN_LEAVE_URL = "/oa/api/employee/getLeanedemp";

    private static final String DEPARTMENT_URL = "/oa/api/dept/getAllDepartment";

    /**
     * 非递归获取部门下的员工
     */
    public List<OaAdminModel> getOaAdminModelList(String deptId) {
        Map<String, String> header = getHttpHeader();
        if (ObjectUtils.isEmpty(header)) {
            return Collections.emptyList();
        }

        Map<String, String> urlParam = new HashMap<>(8);
        urlParam.put("deptId", deptId);
        urlParam.put("type", RECURSION_FLAG);

        Instant start = Instant.now();
        log.info("[OaBizManager]非递归获取部门下的员工开始,args:{},crmTraceId:{}", deptId, ApiContext.getCrmTraceId());
        String response = HttpClientUtil.get(oaApi.concat(ADMIN_URL), header, urlParam);
        log.info("[OaBizManager]非递归获取部门下的员工结束,args:{},result:{},耗时:{}ms,crmTraceId:{}"
                , deptId
                , response
                , Duration.between(start, Instant.now()).toMillis()
                , ApiContext.getCrmTraceId());

        return wrapToOaAdminModelList(response);
    }

    /**
     * 非递归的获取离职员工
     */
    public List<OaAdminModel> getLeaveOaAdminModelList(String startTime, String endTime) {
        Map<String, String> header = getHttpHeader();
        if (ObjectUtils.isEmpty(header)) {
            return Collections.emptyList();
        }

        Map<String, String> urlParam = new HashMap<>(8);
        urlParam.put("begin", startTime);
        urlParam.put("end", endTime);

        Instant start = Instant.now();
        log.info("[OaBizManager]非递归的获取离职员工开始,args:{},crmTraceId:{}", startTime + "~" + endTime, ApiContext.getCrmTraceId());
        String response = HttpClientUtil.postJson(oaApi.concat(ADMIN_LEAVE_URL), header, JSON.toJSONString(urlParam));
        log.info("[DistributeManager]非递归的获取离职员工结束,args:{},result:{},耗时:{}ms,crmTraceId:{}"
                , startTime + "~" + endTime
                , response
                , Duration.between(start, Instant.now()).toMillis()
                , ApiContext.getCrmTraceId());

        return wrapToOaAdminModelList(response);
    }

    /**
     * 获取所有部门信息
     */
    public List<OaDepartmentModel> getOaDepartmentModelList() {
        Map<String, String> header = getHttpHeader();
        if (ObjectUtils.isEmpty(header)) {
            return Collections.emptyList();
        }

        Instant start = Instant.now();
        log.info("[OaBizManager]获取所有部门信息开始,args:{},crmTraceId:{}", "", ApiContext.getCrmTraceId());
        String response = HttpClientUtil.get(oaApi + DEPARTMENT_URL, header, null);
        log.info("[DistributeManager]获取所有部门信息结束,args:{},result:{},耗时:{}ms,crmTraceId:{}"
                , ""
                , response
                , Duration.between(start, Instant.now()).toMillis()
                , ApiContext.getCrmTraceId());

        FeignOaDepartmentResponseModel feignOaDepartmentResponseModel = JSON.parseObject(response, FeignOaDepartmentResponseModel.class);
        if (feignOaDepartmentResponseModel.getCode().equals(ApiResponse.OK_CODE) && CollectionUtils.isNotEmpty(feignOaDepartmentResponseModel.getRows())) {
            return feignOaDepartmentResponseModel.getRows();
        }

        return Collections.emptyList();
    }

    private Map<String, String> getHttpHeader() {
        String oaToken=getOaToken();
        if (StringUtils.isEmpty(oaToken)) {
            return null;
        }

        long time = System.currentTimeMillis();
        String oaSign = md5(APPSECRET + time + APPKEY);
        Map<String, String> header = new HashMap<>(8);
        header.put("Content-Type", "application/json;charset=utf-8");
        header.put("oaToken", oaToken);
        header.put("timestamp", String.valueOf(time));
        header.put("oaSign", oaSign);
        return header;
    }

    public String getOaToken() {
        Instant instant = Instant.now();
        FeignOaTokenResponseModel<OaTokenModel> oaResponseModel = oaClient.generateToken(APPKEY);
        if (ObjectUtils.isEmpty(oaResponseModel.getData())) {
            return null;
        }

        log.info("[OaBizManager]获取人员信息,result:{},耗时:{}ms,crmTraceId:{}"
                , JSON.toJSONString(oaResponseModel.getData())
                , Duration.between(instant, Instant.now()).toMillis()
                , ApiContext.getCrmTraceId());

        return oaResponseModel.getData().getOaToken();
    }

    @SneakyThrows
    private static String md5(String values) {
        StringBuffer buf = new StringBuffer();

        MessageDigest md = MessageDigest.getInstance("MD5");
        md.update(values.getBytes());
        byte b[] = md.digest();

        int i;
        for (int offset = 0; offset < b.length; offset++) {
            i = b[offset];
            if (i < 0) {
                i += 256;
            }
            if (i < 16) {
                buf.append("0");
            }
            buf.append(Integer.toHexString(i));
        }

        return buf.toString();
    }

    private List<OaAdminModel> wrapToOaAdminModelList(String response) {
        FeignOaAdminResponseModel feignOaAdminResponseModel = JSON.parseObject(response, FeignOaAdminResponseModel.class);

        if (ObjectUtils.isEmpty(feignOaAdminResponseModel.getCode())) {
            return Collections.emptyList();
        }

        if (!feignOaAdminResponseModel.getCode().equals(ApiResponse.OK_CODE) || CollectionUtils.isEmpty(feignOaAdminResponseModel.getRows())) {
            return Collections.emptyList();
        }

        List<OaAdminModel> oaAdminModelList = feignOaAdminResponseModel.getRows();
        oaAdminModelList.forEach(item -> item.setMobile(decode(item.getMobile())));
        return oaAdminModelList;
    }

    @SneakyThrows
    private static String decode(String content) {
        byte[] arr = Base64.decodeBase64(content);
        byte[] raw = DEFAULT_KEY.getBytes(StandardCharsets.UTF_8);
        SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, skeySpec);
        byte[] original = cipher.doFinal(arr);
        return new String(original, StandardCharsets.UTF_8);
    }

}
